﻿using Edu.Abstracts;
using Edu.Entitys;
using Edu.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Volo.Abp.Linq;

namespace Edu.Services
{

    public class TeacherUserInfoDto
    {
        public int Rank { get; set; }
        public int AchievementCount { get; set; }
        public int StudentNum { get; set; }

        public JobType Job { get; set; }
    }

    public class TeahcerInfoDto
    {

        public Guid Id { get; set; }
        public int Rating { get; internal set; }

        public string Name { get; internal set; }
        public string Area { get; internal set; }
        public string Avatar { get; internal set; }
        public int CurrentNum { get; internal set; }
        public int TotalNum { get; internal set; }
        public JobType Job { get; internal set; }
    }



    public class TeacherAppService : WeChatAppServiceBase
    {
        public IRepository<AppTeacher, Guid> Repository { get; }

        private IRepository<AppStudent, Guid> appStudents;
        private IAppUserRepository appUsers;
        private IdentityUserManager userManager;

        private RankAppService rankAppService;
        private UserAchievementAppService userAchievementAppService;

        public DefaultAsyncQueryableExecuter AsyncQueryableExecuter { get; }
        public TeacherAppService(IRepository<AppTeacher, Guid> appteachers,
            IRepository<AppStudent, Guid> appStudents,
            IAppUserRepository appUsers,
            IdentityUserManager userManager,
            RankAppService rankAppService,
            UserAchievementAppService userAchievementAppService
        )
        {
            this.Repository = appteachers;
            this.appStudents = appStudents;
            this.appUsers = appUsers;
            this.userManager = userManager;
            AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance;
            this.rankAppService = rankAppService;
            this.userAchievementAppService = userAchievementAppService;
        }

        public async Task<TeacherUserInfoDto> GetTeacherInfo()
        {
            var teacher = this.Repository.Single(a => a.UserId == this.CurrentUser.Id.Value);

            return new TeacherUserInfoDto()
            {
                StudentNum = await this.GetStudentCount(this.CurrentUser.Id.Value),
                AchievementCount = this.userAchievementAppService.GetAchievementCount(this.CurrentUser.Id.Value),
                Rank = (int)rankAppService.GetTeacherRankNum(this.CurrentUser.Id.Value,teacher.Job),
                Job = teacher.Job
            };
        }

        public async Task<int> GetStudentCount(Guid teacherId)
        {
            var query = this.appStudents.Where(a => a.TeacherId == teacherId);
            return await AsyncQueryableExecuter.CountAsync(query);
        }

        public async Task<PagedResultDto<TeahcerInfoDto>> GetListAsync(PagedAndSortedResultRequestDto input)
        {
            input.MaxResultCount = 100000;
            var query = this.Repository.WithDetails(a => a.User);
            var currentAppUser = await this.appUsers.GetAsync(this.CurrentUser.Id.Value);

            var roles = await userManager.GetRolesAsync(MapToIdentityUser(currentAppUser));

            if (roles.IndexOf("admin-area") != -1)
            {
                query = query.Where(a => a.User.Area == currentAppUser.Area);
            }

            var totalCount = await AsyncQueryableExecuter.CountAsync(query);
            query = query.ApplyPaging(input);
            query.OrderBy(m => m.JoinYear).ThenBy(m => m.Rating);

            var entities = await AsyncQueryableExecuter.ToListAsync(query);
            var result = new List<TeahcerInfoDto>();
            foreach (var item in entities)
            {
                var user = await appUsers.GetAsync(item.UserId);
                var teacher = this.Repository.Single(a => a.UserId == item.UserId);
                var total = await AsyncQueryableExecuter.CountAsync(appStudents.Where(a => a.TeacherId == item.UserId));
                var current = await AsyncQueryableExecuter.CountAsync(appStudents.Where(a => a.TeacherId == item.UserId && a.Status != StudentStatus.Grad));

                result.Add(new TeahcerInfoDto
                {
                    Id = item.UserId,
                    Rating = item.Rating,
                    Area = EduConsts.AreaData[user.Area],
                    Avatar = user.Avatar,
                    Name = user.Name,
                    TotalNum = total,
                    CurrentNum = current,
                    Job = teacher.Job
                });
            }
            return new PagedResultDto<TeahcerInfoDto>(
                 totalCount,
                 result
            );
        }
    }
}
